home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 1 (Walnut Creek)
/
Aminet - June 1993 [Walnut Creek].iso
/
usenet
/
sources
/
volume90
/
util
/
setfont2
/
part01
/
SetFont.cp
< prev
next >
Wrap
Text File
|
1990-03-26
|
10KB
|
310 lines
// =======================================================================
/* SetFont 2.7 - by Dave Haynie
BIX: hazy
Usenet: {uunet|rutgers}!cbmvax!daveh
PLINK: D-Dave H
Drink: Guinness
BUSINESS:
This program is complete, real, and true public domain software.
Do with it what you will as long as you don't remove my name from it.
Feel free to enhance this as you see fit. I may eventually make one
that's better....
ABOUT IT:
SetFont V2.7 cleans up all known bugs in previous SetFont versions.
The code is GREATLY cleaned up and simplified from SetFont V2.0. I no
longer free any fonts that were previously set. V2.0 did too much
freeing, but even with that, it is possible that another program could get
a pointer to the font or font descriptor in a window or screen and choke
if that's freed. That may not be good behavior, but this way's safer. A
future version will probably track fonts opened and closed by SetFont
itsself so that it can reclaim some of it's resources and still be
reasonably safe. Right now I have no way of knowing if the font or
descriptor I see is even really owned by SetFont. SetFont 2.7 also cleans
up the font open ordering, once and for all. Apparently, the font system
is broken or confused. In SetFont 2.5, I opened a disk font first, and
ended up with multiple copies of a single font in RAM. In SetFont 2.6,
I reversed the order and ended up missing disk fonts, as the software
took the closest front to what I wanted from RAM. Now I open both damn
fonts, take the closest to what I'm looking for from the two, and close
the other. Ties go to the RAM font.
CONFLICTS:
There are a few potential problems the general notion of SetFont in
the Amiga system. First of all, many programs are written to support only
the topaz 8 (80 column) font (sloppy, I know, but that's life). If you're
a 60 column user, you've probably experienced this before. It's not a
problem with the Amiga as a whole, since most of the system will adjust
itself. But it may be a problem with programs that have a fixed idea of
what a font should look like. Most 80 column fonts work with most
applications, and an 80 column 8x8 font will work just about everywhere.
Some programs, like CLI for instance, have trouble with proportionally-
spaced fonts. The best thing to do is try out the font you like. One
final problem is that some applications ask the WorkBench screen to close
when they start up. It'll close if there's nothing else open on it, but
when it re-opens, it'll restart with the Preferences-selected font, not
the SetFont selected font. Of course, preferences doesn't support
arbitrary fonts (which is why this program is even necessary). Oh well,
maybe day.
*/
#include <exec/types.h>
#include <exec/io.h>
#include <exec/ports.h>
#include <exec/memory.h>
#include <graphics/gfxbase.h>
#include <graphics/text.h>
#include <graphics/rastport.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <intuition/intuition.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
// =========================================================================
// Miscellaneous stuff.
extern TextFont *OpenDiskFont(const TextAttr *);
inline BPTR CADDR(APTR cptr) { return BPTR(ULONG(cptr) >> 2); }
inline void fail(char *a, char *b = NULL) { printf(a,b); exit(10); }
inline UWORD abs(UWORD x) { return (x > 0)?x:(-x); }
inline MsgPort *contask(MsgPort *port) {
return (MsgPort *) ((port->mp_SigTask->ln_Type == NT_PROCESS)
? ((Process *)port->mp_SigTask)->pr_ConsoleTask
: NULL);
}
// =========================================================================
// This is the "smart" font class. SmartFont items stay around after the
// program exits if they appear to have been used. As it turns out, the
// Amiga font system looks somewhat broken. If I OpenDiskFont(), I load
// the font, even if it's in memory. If I OpenFonr(), I get the closest
// match to the font I want from the list of fonts in memory, not the
// big picture. So SmartFont now gets a bit smarter, and knows how to
// find the best match from both possible sources. The font opening order
// is important, since if I fetch a disk font, I'm sure to find it in RAM
// afterward.
class SmartFont {
private:
static BOOL aok; // Font checks out
TextAttr sfattr; // Font descriptor
public:
SmartFont(char *n, UWORD s);
TextFont *font();
TextAttr *attr() {
TextAttr *a = (TextAttr *)AllocMem(sizeof(TextAttr),MEMF_PUBLIC|MEMF_CLEAR);
a->ta_Name = (char *)AllocMem(strlen(sfattr.ta_Name)+1,MEMF_PUBLIC|MEMF_CLEAR);
strcpy(a->ta_Name,sfattr.ta_Name);
a->ta_YSize = sfattr.ta_YSize;
return a;
}
char *name() { return sfattr.ta_Name; }
UWORD size() { return sfattr.ta_YSize; }
};
SmartFont::SmartFont(char *n, UWORD s = 8) {
strcat(strcpy(sfattr.ta_Name = new char[strlen(n)+6],n),".font");
sfattr.ta_YSize = (s>2)?s:8;
sfattr.ta_Style = sfattr.ta_Flags = 0;
if (!aok) {
TextFont *f = font();
CloseFont(f);
aok = TRUE;
}
}
TextFont *SmartFont::font() {
TextFont *memf, *dskf;
if ((memf = OpenFont(&sfattr)) && sfattr.ta_YSize == memf->tf_YSize)
return memf;
dskf = OpenDiskFont(&sfattr);
if (!memf && !dskf) fail("Font \"%s\" not found\n",sfattr.ta_Name);
if (!memf && dskf)
return dskf;
else if (!dskf && memf)
return memf;
else if (abs(sfattr.ta_YSize - memf->tf_YSize) <=
abs(sfattr.ta_YSize - dskf->tf_YSize)) {
CloseFont(dskf);
return memf;
}
CloseFont(memf);
return dskf;
}
// =========================================================================
// These classes manage the places that fonts are hidden.
// This is the basic place node
class PlaceNode : public Node {
private:
static Window *pwin;
static Screen *pscr;
public:
PlaceNode();
PlaceNode *next() { return (PlaceNode *)Node::next(); }
void testwindow() { if (!pwin) fail("Window not found\n"); }
void testscreen() { if (!pscr) fail("Screen not found\n"); }
Window *window() { return pwin; }
Screen *screen() { return pscr; }
virtual void set(SmartFont *f) {
testwindow();
SetFont(window()->graphic(),f->font());
printf("\033c"); // Re-init window's conunit
(void)flushall();
}
};
// Initialize the static stuff, once.
PlaceNode::PlaceNode() {
if (pwin) return;
StandardPacket *packet = new StandardPacket;
InfoData *info = new InfoData;
MsgPort *port = new StdPort;
// Find the window
if (contask(port)) {
packet->sendio(contask(port),port,ACTION_DISK_INFO,CADDR(info));
(void)port->wait();
pwin = (Window *)info->id_VolumeNode;
} else
pwin = NULL;
delete port;
delete info;
delete packet;
// Find the screen
pscr = (pwin) ? pwin->screen() : NULL;
}
// These are the derived special nodes, one for each "place".
#define WindowNode PlaceNode
class ScreenNode : public PlaceNode {
public:
void set(SmartFont *f) {
testscreen();
if (strcmp(screen()->Font->ta_Name,f->name()) == 0)
screen()->Font->ta_YSize = f->size();
else
screen()->Font = f->attr();
}
};
class TitleNode : public PlaceNode {
public:
void set(SmartFont *f) {
testscreen();
SetFont(screen()->graphic(),f->font());
}
};
class BarNode : public PlaceNode {
public:
void set(SmartFont *f) {
testscreen();
SetFont(screen()->BarLayer->rp,f->font());
}
};
// This is the place list, which links a number of place nodes, and also
// manages to go work like finding windows, etc.
class PlaceList : public List {
public:
PlaceList(int argc, char **argv);
PlaceNode *first() { return (PlaceNode *)List::first(); }
};
// The PlaceList constructor does a great deal of the work. It looks up
// the window data, then parses the command line to build the place
// list.
PlaceList::PlaceList(int argc, char **argv) {
// Parse our input arguments
for (short i = 0; i < argc; ++i)
switch (toupper(argv[i][0])) {
case 'B': add(new BarNode); break;
case 'S': add(new ScreenNode); break;
case 'T': add(new TitleNode); break;
case 'W': add(new WindowNode); break;
default : break;
}
if (is_empty()) {
add(new BarNode);
add(new ScreenNode);
add(new TitleNode);
add(new WindowNode);
}
}
// =========================================================================
// Prints help notice
void PrintNotice() {
printf("SetFont V2.7 by Dave Haynie\n\n");
printf("Usage: SetFont [fontname [point [place]]]\n");
printf(" where:\n");
printf(" \2331mfontname\2330m is the font's name (e.g. \"topaz\")\n");
printf(" \2331mpoint\2330m is the point size (default is 8)\n");
printf(" \2331mplace\2330m pick the place, one or more of:\n");
printf(" \2331mBAR\2330m set the barlayer font only\n");
printf(" \2331mSCREEN\2330m set the screen font only\n");
printf(" \2331mTITLES\2330m set the screen titles only\n");
printf(" \2331mWINDOW\2330m set the window's font only\n\n");
printf("If no \2331mplace\2330m switch is given, everything is set.\n\n");
exit(0);
}
// The main function
void main(int argc, char *argv[]) {
// Automatic help command
if (argc < 2 || argv[1][0] == '?') PrintNotice();
// Process the command-line arguments, AmigaDOS style.
PlaceList *plist = new PlaceList(argc-2,&argv[3]);
// Get the font if it's there.
SmartFont *font = new SmartFont(argv[1],atoi(argv[2]));
// Here we apply all the requested changes.
for (PlaceNode *n = plist->first(); n->next(); n = n->next()) n->set(font);
// And we're done!
exit(0);
}